package pkg

import (
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"

	"github.com/flosch/pongo2"
)

func DirExists(dir string) bool {
	r := true
	_, err := os.Stat(dir)
	if err != nil {
		if os.IsNotExist(err) {
			r = false
		} else {
			fmt.Println("Error:", err)
		}
	}
	return r
}

// 更改文件后缀名
func ChEndFileName(rootDir string) {
	err := filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if !info.IsDir() && filepath.Ext(path) == ".go" {
			newPath := path[:len(path)-3] + ".tpl"
			fmt.Printf("Renaming %s to %s\n", path, newPath)
			return os.Rename(path, newPath)
		}
		return nil
	})
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}
}

// 遍历指定目录下的所有tpl模版文件，然后按入参里的结构体进行替换
func RenderTpl2Go(params pongo2.Context, tplPath string, outPath string) {
	// 从tpl文件读取模板
	tpl, err := pongo2.FromFile(tplPath)
	if err != nil {
		panic(err)
	}
	// 执行模板替换并输出结果
	result, err := tpl.Execute(params)
	if err != nil {
		panic(err)
	}
	//获得tpl·文件的文件名
	goFile := outPath + "/" + filepath.Base(tplPath)[:len(filepath.Base(tplPath))-4] + ".go"
	fmt.Printf("Writing %s\n", goFile)
	//创建并写入goFile路径和目录文件
	if !DirExists(filepath.Dir(goFile)) {
		err = os.MkdirAll(filepath.Dir(goFile), 0755)
		if err != nil {
			panic(err)
		}
		f, err := os.Create(goFile)
		if err != nil {
			panic(err)
		}
		defer f.Close()
		err = os.WriteFile(goFile, []byte(result), 0644)
		if err != nil {
			panic(err)
		}
	}
}

func RenderTpl2Git(params pongo2.Context, tplPath string, outPath string) {
	// 从tpl文件读取模板
	tpl, err := pongo2.FromFile(tplPath)
	if err != nil {
		panic(err)
	}
	// 执行模板替换并输出结果
	result, err := tpl.Execute(params)
	if err != nil {
		panic(err)
	}
	//获得tpl·文件的文件名
	goFile := outPath + "/." + filepath.Base(tplPath)[:len(filepath.Base(tplPath))-4]
	fmt.Printf("Writing %s\n", goFile)
	//创建并写入goFile路径和目录文件
	if !DirExists(filepath.Dir(goFile)) {
		err = os.MkdirAll(filepath.Dir(goFile), 0755)
		if err != nil {
			panic(err)
		}
		f, err := os.Create(goFile)
		if err != nil {
			panic(err)
		}
		defer f.Close()
		err = os.WriteFile(goFile, []byte(result), 0644)
		if err != nil {
			panic(err)
		}
	}
}

// 遍历指定目录下的所有tpl后缀的文件
func ScanTplFiles(rootDir string) []string {
	var tplFiles []string
	err := filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if !info.IsDir() && filepath.Ext(path) == ".tpl" {
			tplFiles = append(tplFiles, path)
		}
		return nil
	})
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}
	return tplFiles
}

// 获取当前go版本号
func GetGoVersion() string {
	cmd := exec.Command("go", "version")
	output, err := cmd.Output()
	if err != nil {
		fmt.Printf("获取Go版本信息出错: %v\n", err)
		return ""
	}
	fmt.Printf("当前Go版本: %s", string(output))
	return string(output)
}

// 渲染指定模版
func Render(app, subApp, m string) {
	curPath, _ := os.Getwd()
	RelPath := filepath.Join("/tpl", m)
	appSubPath := filepath.Join(curPath, app, subApp)
	fmt.Println("渲染模版：" + appSubPath)
	if !DirExists(appSubPath) {
		tplPkgPath := curPath + RelPath
		paths := ScanTplFiles(tplPkgPath)
		fmt.Println(paths, tplPkgPath)

		for _, file := range paths {
			relPath, _ := filepath.Rel(tplPkgPath, filepath.Dir(file))
			outPath := filepath.Join(appSubPath, relPath)
			RenderTpl2Go(pongo2.Context{
				"app":    app,
				"subApp": subApp,
			}, file, outPath)
		}
	} else {
		fmt.Println(appSubPath, "已存在，跳过")
	}
}

// CopyGitignore 用于将源.gitignore文件拷贝到目标目录
func CopyTo(srcFile string, destFile string) error {
	// 打开源.gitignore文件
	src, err := os.Open(srcFile)
	if err != nil {
		return err
	}
	defer src.Close()

	dst, err := os.Create(destFile)
	if err != nil {
		return err
	}
	defer dst.Close()
	// 从源文件读取内容并写入到目标文件
	_, err = io.Copy(dst, src)
	if err != nil {
		return err
	}

	return nil
}
